#include "common.h"

volatile struct rcc_reg *rcc = (volatile struct rcc_reg *)0x40021000;

void init_rcc(void)
{
    rcc->CR |= (1 << 0);  // 使用内部高速时钟
    while (!(rcc->CR & (1 << 1)))
        ;  // 等待内部高速时钟

    rcc->CFGR &= ~(3 << 0);  // 使用内部高速时钟作为系统时钟
    while ((rcc->CFGR & (3 << 2)))
        ;  // 等待系统时钟作为内部高速时钟

    rcc->CR &= ~(1 << 24);  // 禁止PLL
    while ((rcc->CR & (1 << 25)))
        ;  // 等待PLL未锁定

    rcc->CR &= ~(1 << 16);  // 关闭外部高速时钟
    while (rcc->CR & (1 << 17))
        ;                   // 等待外部高速时钟没有就绪
    rcc->CR &= ~(1 << 18);  // 外部高速时钟没有旁路

    rcc->CFGR &= ~(1 << 17);  // 外部高速时钟1分频后作为PLL的输入,8M/1 = 8M
    rcc->CFGR |= (1 << 16);   // 外部高速时钟作为PLL的输入
    rcc->CFGR &= ~(0b1111 << 18);
    rcc->CFGR |= (0b0111 << 18);  // PLL经过12倍频后输出8M*9=72M
    rcc->CFGR &= ~(1 << 22);      // PLL/1.5作为USB时钟48M
    rcc->CFGR &= ~(0b1111 << 4);  // AHB时钟不分频72M
    rcc->CFGR &= ~(0b111 << 8);
    rcc->CFGR |= (0b100 << 8);    // APB1二分频72M/2=36M
    rcc->CFGR &= ~(0b111 << 11);  // APB2不分频72M
    rcc->CFGR &= ~(0b11 << 14);
    rcc->CFGR |= (0b10 << 14);  // ADC为PLCK2的6分频72M/6 = 12M

    rcc->CR |= (1 << 16);  // 开启外部高速时钟
    while (!(rcc->CR & (1 << 17)))
        ;  // 等待外部高速时钟就绪

    rcc->CR |= (1 << 24);  // 使能PLL
    while (!(rcc->CR & (1 << 25)))
        ;  // 等待PLL锁定

    rcc->CFGR |= (rcc->CFGR & (~(0b11 << 0))) | (0b10 << 0);  // 使用PLL作为系统时钟
    while ((0b10 << 2) != (rcc->CFGR & (0b11 << 2)))
        ;
}
